#include "Logger.h"
#include "LogMessage.hpp"

void mylog::Logger::logWithLevel(LogLevel::Level level, const std::string& file,
                                 size_t line, const char* fmt, va_list ap) {
    if (level < _limit_level)
        return;              // 1. 判断当前日志能否输出
    char* payload = nullptr; // 2. 形成有效载荷字符串
    if (vasprintf(&payload, fmt, ap) == -1)
        throw std::runtime_error("vasprintf fail");
    LogMessage msg(level, _logger, file, line,
                   std::string(payload)); // 3. 形成LogMessage结构体
    std::string log_message = _formatter->Format(msg); // 4. 形成日志消息字符串
    log(log_message.c_str(), log_message.size());
    free(payload);
}

void mylog::Logger::Info(const std::string& file, size_t line, const char* fmt,
                         ...) {
    va_list ap;
    va_start(ap, fmt);
    logWithLevel(LogLevel::Level::INFO, file, line, fmt, ap);
    va_end(ap);
}

void mylog::Logger::Warning(const std::string& file, size_t line,
                            const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    logWithLevel(LogLevel::Level::WARNING, file, line, fmt, ap);
    va_end(ap);
}

void mylog::Logger::Debug(const std::string& file, size_t line, const char* fmt,
                          ...) {
    va_list ap;
    va_start(ap, fmt);
    logWithLevel(LogLevel::Level::DEBUG, file, line, fmt, ap);
    va_end(ap);
}

void mylog::Logger::Error(const std::string& file, size_t line, const char* fmt,
                          ...) {
    va_list ap;
    va_start(ap, fmt);
    logWithLevel(LogLevel::Level::ERROR, file, line, fmt, ap);
    va_end(ap);
}

void mylog::Logger::Fatal(const std::string& file, size_t line, const char* fmt,
                          ...) {
    va_list ap;
    va_start(ap, fmt);
    logWithLevel(LogLevel::Level::FATAL, file, line, fmt, ap);
    va_end(ap);
}

void mylog::SyncLogger::log(const char* data, size_t len) {
    std::unique_lock<std::mutex> ulk(_mtx);
    for (auto& sink : _sinks) {
        if (sink.get() != nullptr)
            sink->log(data, len);
    }
}

void mylog::AsyncLogger::RealSink(Buffer& buf) {
    // 异步线程根据落地方向进行数据落地
    for (auto& sink : _sinks) {
        if (sink.get() != nullptr)
            sink->log(buf.Start(), buf.ReadableSize());
    }
}

mylog::Logger::ptr mylog::LocalLoggerBuilder::Build() {
    // 不能没有日志器名称
    assert(!_logger_name.empty());

    // 如果用户没有手动设置过格式化器，就进行构造一个默认的格式化器
    if (_formatter.get() == nullptr)
        _formatter = std::make_shared<Formatter>();

    // 如果用户没有手动设置过落地方向数组，就进行默认设置一个的落地到标准输出的格式化器
    if (_sinks.empty())
        _sinks.push_back(SinkFactory::create<StdOutSink>());

    // 根据日志器的类型构造相应类型的日志器
    if (_logger_type == LoggerType::Async_Logger) {
        return std::make_shared<AsyncLogger>(_logger_name, _limit, _formatter,
                                             _sinks, _async_type);
    }
    return std::make_shared<SyncLogger>(_logger_name, _limit, _formatter,
                                        _sinks);
}

mylog::Logger::ptr mylog::GlobalLoggerBuilder::Build() {
    assert(!_logger_name.empty());
    if (_formatter.get() == nullptr)
        _formatter = std::make_shared<Formatter>();
    if (_sinks.empty())
        _sinks.push_back(SinkFactory::create<StdOutSink>());

    Logger::ptr logger;
    if (_logger_type == LoggerType::Async_Logger) {
        logger = std::make_shared<AsyncLogger>(_logger_name, _limit, _formatter,
                                               _sinks, _async_type);
    } else {
        logger = std::make_shared<SyncLogger>(_logger_name, _limit, _formatter,
                                              _sinks);
    }
    LogManager::GetInstance().AddLogger(logger);
    return logger;
}
